#pragma once

#include <iostream>
#include <memory>
// #include <jsoncpp/json/json.h>
using namespace std;
namespace Protocol
{
const string ProSep = " ";
string lineBreakSep = "\n";
string Encode(const std::string &message)
{
    string len = to_string(message.size());
    string package = len + lineBreakSep + message + lineBreakSep;
    return package;
}
bool Decode(std::string &package, std::string *message)
{
    auto pos = package.find(lineBreakSep);
    if (pos == string::npos)
        return false;
    string lens = package.substr(0, pos);
    int messagelen = stoi(lens);
    int total = lens.size() + messagelen + 2 * lineBreakSep.size();
    if (package.size() < total)
            return false;
    *message = package.substr(pos + lineBreakSep.size(), messagelen);
    package.erase(0, total);
    return true;
}
class Request
{
public:
    Request() : _data_x(0), _data_y(0), _oper(0)
    {
    }
    Request(int x, int y, char oper) : _data_x(x), _data_y(y), _oper(oper)
    {
    }
    void Debug()
    {
        cout << "_data_x:" << _data_x << endl;
        cout << "_data_y:" << _data_y << endl;
        cout << "char oper:" << _oper << endl;
    }
    void Inc()
    {
        _data_x++;
        _data_y++;
    }
    // 结构化数据->字符串
    bool Serialize(std::string *out)
    {
        *out = to_string(_data_x) + ProSep + _oper + ProSep + to_string(_data_y);
        return true;
    }

    // 字符串->结构化数据
    bool Deserialize(std::string &in) // "x y" [)
    {
        auto left = in.find(ProSep);
        if (left == string::npos)
            return false;
        auto right = in.rfind(ProSep);
        if (left == string::npos)
            return false;
        _data_x = stoi(in.substr(0, left));
        _data_y = stoi(in.substr(right + ProSep.size()));
        string oper = in.substr(left + ProSep.size(), right - (left + ProSep.size()));
        if (oper.size() != 1)
            return false;
        _oper = oper[0];
        return true;
    }
    int Getx() { return _data_x; }
    int Gety() { return _data_y; }
    char GetOper() { return _oper; }
    ~Request()
    {
    }

private:
    int _data_x;
    int _data_y;
    char _oper;
};
class Response
{
public:
    Response() : _result(0), _code(0)
    {
    }
    Response(int result, int code) : _result(result), _code(code)
    {
    }
    // 结构化数据->字符串
    bool Serialize(std::string *out)
    {
        *out = to_string(_result) + ProSep + to_string(_code);
        return true;
    }
    // 字符串->结构话数据
    bool Deserialize(std::string &in)
    {
        auto pos = in.find(ProSep);
        if (pos == string::npos)
            return false;
        _result = stoi(in.substr(0, pos));
        _code = stoi(in.substr(pos + ProSep.size()));
        return true;
    }
    void SetResult(int res) { _result = res; }
    void SetCode(int code) { _code = code; }
    int GetResult() { return _result; }
    int GetCode() { return _code; }
    ~Response()
    {
    }

private:
    int _result;
    int _code;
};
class Factory
    {
    public:
        std::shared_ptr<Request> BuildRequest()
        {
            std::shared_ptr<Request> req = std::make_shared<Request>();
            return req;
        }
        std::shared_ptr<Request> BuildRequest(int x, int y, char op)
        {
            std::shared_ptr<Request> req = std::make_shared<Request>(x, y, op);
            return req;
        }
        std::shared_ptr<Response> BuildResponse()
        {
            std::shared_ptr<Response> resp = std::make_shared<Response>();
            return resp;
        }
        std::shared_ptr<Response> BuildResponse(int result, int code)
        {
            std::shared_ptr<Response> req = std::make_shared<Response>(result, code);
            return req;
        }
    };
}